
package com.young.rpc.handler;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.young.common.Config;
import com.young.domain.JobExecuteResultEnum;
import com.young.job.JobContext;

import java.io.*;
import java.net.HttpURLConnection;

/**
 * @description：处理 http 请求并执行任务作业
 * @author: yangyahui01
 * @date: 11/25/24 3:05 PM
 */
public class DefaultHttpJobHandler implements HttpHandler {

    public static final String APPLICATION_JSON = "application/json; charset=UTF-8";

    private static final GsonBuilder GSON_BUILDER = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss.SSS");

    private final LocalByteArray response = new LocalByteArray();


    /**
     * 从构造方法注入，用于执行业务逻辑
     */
    private final JobHandler<JobExecuteResultEnum> jobHandler;

    public DefaultHttpJobHandler(JobHandler<JobExecuteResultEnum> jobHandler) {
        this.jobHandler = jobHandler;
    }

    public void handle(HttpExchange httpExchange) throws IOException {

        /**
         * 解析 http 请求
         */
        JobContext jobContext = context(httpExchange);

        OutputStreamWriter osw = null;

        ByteArrayOutputStream outputStream = null;

        try {
            /**
             * 去执行业务端的方法
             */
            JobExecuteResultEnum jobExecuteResultEnum = jobHandler.doJob(jobContext);

            JsonObject responseBody = response(jobExecuteResultEnum);

            outputStream = this.response.get();

            outputStream.reset();

            osw = new OutputStreamWriter(outputStream);


            osw.write(responseBody.toString());

            osw.flush();
            outputStream.flush();


            httpExchange.getResponseHeaders().set("Content-Type",
                    APPLICATION_JSON);
            httpExchange.getResponseHeaders().set("Content-Length",
                    String.valueOf(outputStream.size()));
            httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, outputStream.size());
            outputStream.writeTo(httpExchange.getResponseBody());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(osw != null) {
                    osw.close();
                }
                if(outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            httpExchange.close();
        }
    }


    /**
     * 解析 http 请求，构建 JobContext 上下文
     * @param httpExchange 该对象代表一个 HTTP 请求和响应的交换
     * @return JobContext
     */
    private JobContext context(HttpExchange httpExchange) {

        JobContext jobContext = null;

        StringBuffer stringBuffer = new StringBuffer();

        BufferedReader bufferedReader = null;

        String line = null;

        try {
            bufferedReader = new BufferedReader(new InputStreamReader(httpExchange.getRequestBody()));

            while ((line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line.trim());
            }
            jobContext = GSON_BUILDER.create().fromJson(stringBuffer.toString(), JobContext.class);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {}
        }
        return jobContext;
    }

    /**
     * 解析任务执行返回的枚举
     * @param jobExecuteResultEnum
     * @return
     */
    private JsonObject response(JobExecuteResultEnum jobExecuteResultEnum) {
        JsonObject response = new JsonObject();
        response.addProperty("version", Config.VERSION);
        switch (jobExecuteResultEnum){
            case SUCCESS:
                response.addProperty("status",JobExecuteResultEnum.SUCCESS.getStatus());
                response.addProperty("message","节点调度成功");
                break;
            case CLIENT_NOT_EXIST:
                response.addProperty("status",JobExecuteResultEnum.CLIENT_NOT_EXIST.getStatus());
                response.addProperty("message","节点的任务类或方法不存在");
                break;
            case CLIENT_ERROR:
            default:
                response.addProperty("status",JobExecuteResultEnum.CLIENT_ERROR.getStatus());
                response.addProperty("message","客户端执行任务错误");
                break;
        }
        return response;
    }

    private static class LocalByteArray extends ThreadLocal<ByteArrayOutputStream> {
        protected ByteArrayOutputStream initialValue()
        {
            return new ByteArrayOutputStream(1 << 20);
        }
    }
}
